package com.ruoyi.common.qy.utils;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class VideoDownloaderJava8 {

    /**
     * 下载视频文件
     * @param videoUrl 视频URL地址
     * @param outputPath 输出文件路径
     * @throws IOException 下载异常
     */
    public static void downloadVideo(String videoUrl, String outputPath) throws IOException {
        URL url = new URL(videoUrl);
        Path outputFile = Paths.get(outputPath);

        // 确保目录存在
        Path parentDir = outputFile.getParent();
        if (parentDir != null && !Files.exists(parentDir)) {
            Files.createDirectories(parentDir);
        }

        // 使用try-with-resources确保资源正确关闭
        try (ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream())) {
            Files.copy(Channels.newInputStream(readableByteChannel), outputFile);
        }

        System.out.println("视频下载完成: " + outputPath);
    }

    /**
     * 带进度显示的视频下载
     * @param videoUrl 视频URL地址
     * @param outputPath 输出文件路径
     * @throws IOException 下载异常
     */
    public static void downloadVideoWithProgress(String videoUrl, String outputPath) throws IOException {
        URL url = new URL(videoUrl);
        Path outputFile = Paths.get(outputPath);

        // 确保目录存在
        Path parentDir = outputFile.getParent();
        if (parentDir != null && !Files.exists(parentDir)) {
            Files.createDirectories(parentDir);
        }

        try (ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream());
             FileChannel fileChannel = FileChannel.open(outputFile,
                     StandardOpenOption.CREATE,
                     StandardOpenOption.WRITE,
                     StandardOpenOption.TRUNCATE_EXISTING)) {

            // 获取文件大小（如果服务器提供）
            long fileSize = getFileSize(url);
            long totalBytesTransferred = 0;
            long bytesTransferred;

            do {
                bytesTransferred = fileChannel.transferFrom(readableByteChannel, totalBytesTransferred, 8192);
                totalBytesTransferred += bytesTransferred;

                // 显示进度
                if (fileSize > 0) {
                    int progress = (int) ((totalBytesTransferred * 100) / fileSize);
                    System.out.printf("\r下载进度: %d%% [%d/%d bytes]",
                            progress, totalBytesTransferred, fileSize);
                } else {
                    System.out.printf("\r已下载: %d bytes", totalBytesTransferred);
                }
            } while (bytesTransferred > 0);

            System.out.println("\n视频下载完成: " + outputPath);
        }
    }

    /**
     * 获取远程文件大小
     * @param url 文件URL
     * @return 文件大小，如果无法获取返回-1
     */
    private static long getFileSize(URL url) {
        try {
            java.net.URLConnection connection = url.openConnection();
            return connection.getContentLengthLong();
        } catch (IOException e) {
            return -1;
        }
    }

    /**
     * 批量下载视频
     * @param videoUrls 视频URL数组
     * @param outputDir 输出目录
     */
    public static void batchDownload(String[] videoUrls, String outputDir) {
        Path outputPath = Paths.get(outputDir);
        if (!Files.exists(outputPath)) {
            try {
                Files.createDirectories(outputPath);
            } catch (IOException e) {
                System.err.println("创建目录失败: " + e.getMessage());
                return;
            }
        }

        // 使用Java 8 Stream并行下载
        java.util.Arrays.stream(videoUrls)
            .parallel()
            .forEach(url -> {
                try {
                    String fileName = getFileNameFromUrl(url);
                    String filePath = outputPath.resolve(fileName).toString();
                    downloadVideo(url, filePath);
                } catch (IOException e) {
                    System.err.println("下载失败: " + url + " - " + e.getMessage());
                }
            });
    }

    /**
     * 从URL中提取文件名
     * @param url 视频URL
     * @return 文件名
     */
    private static String getFileNameFromUrl(String url) {
        String fileName = url.substring(url.lastIndexOf('/') + 1);
        // 如果URL包含查询参数，需要去除
        if (fileName.contains("?")) {
            fileName = fileName.substring(0, fileName.indexOf('?'));
        }
        return fileName.isEmpty() ? "video.mp4" : fileName;
    }

    /**
     * 使用传统IO方式下载（备选方案）
     * @param videoUrl 视频URL
     * @param outputPath 输出路径
     * @throws IOException 下载异常
     */
    public static void downloadVideoTraditional(String videoUrl, String outputPath) throws IOException {
        URL url = new URL(videoUrl);
        Path outputFile = Paths.get(outputPath);

        // 确保目录存在
        Path parentDir = outputFile.getParent();
        if (parentDir != null && !Files.exists(parentDir)) {
            Files.createDirectories(parentDir);
        }

        try (InputStream inputStream = url.openStream()) {
            Files.copy(inputStream, outputFile);
        }

        System.out.println("视频下载完成: " + outputPath);
    }

    public static void main(String[] args) {
        try {
            // 基本下载示例
            String videoUrl = "https://example.com/video.mp4";
            String outputPath = "downloads/video.mp4";

            System.out.println("开始下载视频...");
            downloadVideo(videoUrl, outputPath);

            // 带进度显示的下载
            System.out.println("\n开始带进度下载...");
            downloadVideoWithProgress(videoUrl, "downloads/video_with_progress.mp4");

            // 批量下载示例
            String[] urls = {
                "https://example.com/video1.mp4",
                "https://example.com/video2.mp4",
                "https://example.com/video3.mp4"
            };

            System.out.println("\n开始批量下载...");
            batchDownload(urls, "downloads/batch");

        } catch (IOException e) {
            System.err.println("下载失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
